<?php

namespace App\Services\Payment\PayCore\zhongxin;

use App\Services\Payment\PayCore\zhongxin\lib\ClientResponseHandler;
use App\Services\Payment\PayCore\zhongxin\lib\RequestHandler;
use App\Services\Payment\PayCore\zhongxin\lib\PayHttpClient;
use App\Services\Payment\PayCore\zhongxin\lib\Utils;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use App\Helpers\SnHelper;

class ZhongxinPayService
{
    /**
     * 交易请求地址
     *
     */
    public $post_url = 'https://pay.swiftpass.cn/pay/gateway';
    public $version = '2.0';

    private $resHandler = null;
    private $reqHandler = null;
    private $pay = null;
    private $appid = '';
    private $mchId = '';
    private $key= '';//新版已舍弃该参数
    private $debug= false;
    private $public_rsa_key= '';//威富通RSA公钥
    private $private_rsa_key= '';//商户自行生成的RSA私钥

    /**
     * ZhongxinPayService constructor.
     * @param $config
     * @throws \Exception
     */
    public function __construct($config)
    {
        if(empty($config['appid']) && empty($config['debug'])){
            throw new \Exception('appid不能为空');
        }

        if(empty($config['mchId'])){
            throw new \Exception('mchId不能为空');
        }

        if(empty($config['public_rsa_key'])){
            throw new \Exception('public_rsa_key不能为空');
        }

        if(empty($config['private_rsa_key'])){
            throw new \Exception('private_rsa_key不能为空');
        }

        $this->appid = $config['appid'];
        $this->key = empty($config['key'])?'':$config['key'];
        $this->public_rsa_key = $config['public_rsa_key'];
        $this->private_rsa_key = $config['private_rsa_key'];
        $this->debug = $config['debug'];

        $this->resHandler = new ClientResponseHandler();
        $this->reqHandler = new RequestHandler();
        $this->pay = new PayHttpClient();

        $this->reqHandler->setGateUrl($this->post_url);

        if(!empty($this->public_rsa_key) && !empty($this->private_rsa_key)){
            $this->reqHandler->setSignType('RSA_1_256');
            $this->reqHandler->setRSAKey($this->private_rsa_key);

            $this->resHandler->setRSAKey($this->public_rsa_key);
            $this->resHandler->setSignType('RSA_1_256');

            $this->reqHandler->setParameter('sign_type','RSA_1_256');
            $this->resHandler->setParameter('sign_type','RSA_1_256');
        }else{
            $this->reqHandler->setSignType('MD5');
            $this->reqHandler->setKey($config['key']);

            $this->resHandler->setKey($config['key']);
            $this->resHandler->setSignType('MD5');

            $this->reqHandler->setParameter('sign_type','MD5');
            $this->resHandler->setParameter('sign_type','MD5');
        }

        $this->mchId = $config['mchId'];


    }

    /**
	 * 统一下单接口
     *
     * @param $data
     *
     * @return array
     */
    public function pay($data){
        if(empty($this->mchId)){
            return ['code'=>1,'msg'=>'此商城支付系统正在升级'];
        }

        if(empty($data['trade_type'])){
            return ["code"=>1,"msg"=>'交易类型不能为空'];
        }

        if(!in_array($data['trade_type'],['JSAPI','NATIVE'])){
            return ["code"=>1,"msg"=>'交易类型错误'];
        }

        if(empty($data['body'])){
            return ["code"=>1,"msg"=>'商品描述不能为空'];
        }

        if(empty($data['out_trade_no'])){
            return ["code"=>1,"msg"=>'商户订单号不能为空'];
        }

        if(empty($data['notifyUrl'])){
            return ["code"=>1,"msg"=>'异步通知地址不能为空'];
        }

        if(empty($data['total_fee'])){
            return ["code"=>1,"msg"=>'交易金额不能为空'];
        }

        if($data['trade_type'] == 'JSAPI'){
            unset($data['trade_type']);
            return $this->jsapiPay($data);
        }elseif($data['trade_type'] == 'NATIVE'){
            unset($data['trade_type']);
            return $this->nativePay($data);
        }
    }

    /**
     * 扫码支付接口
     *
     * @param $data
     * ------------------------------------ 必填字段 -------------------------------------------
     * @param string $data['service']  必填 默认值:pay.weixin.native   接口类型     String(32)
     * @param string $data['mch_id']  必填   商户号  String(32)
     *
     * @param string $data['out_trade_no']     必填  商户订单号  String(32)
     * @param string $data['body']   必填  商品描述  String(127)
     * @param string $data['total_fee']       必填  总金额  Int
     * @param string $data['mch_create_ip']  必填   终端IP  String(16)
     * @param string $data['notify_url']  必填   通知地址  String(255)
     * @param string $data['nonce_str']      必填   随机字符串  String(32)
     * @param string $data['sign']   必填  签名  String(32)
     *
     * ------------------------------------ 选填字段 -------------------------------------------
     * @param string $data['version']     选填  版本号，version默认值是2.0  String(8)
     * @param string $data['charset']     选填  字符集，默认为 UTF-8  String(8)
     * @param string $data['sign_type']     选填  签名方式，默认：MD5 String(8)
     * @param string $data['device_info']     选填  设备号  String(32)
     * @param string $data['attach']     选填  商户附加信息，可做扩展参数  String(127)
     * @param string $data['time_start']     选填  订单生成时间，订单生成时间，格式为yyyyMMddHHmmss 注：订单生成时间与超时时间需要同时传入才会生效。 String(14)
     * @param string $data['time_expire']     选填  订单失效时间，格式为yyyyMMddHHmmss 注：订单生成时间与超时时间需要同时传入才会生效。 String(14)
     * @param string $data['op_user_id']     选填  操作员，默认为商户号  String(32)
     * @param string $data['goods_tag']     选填  商品标记  String(32)
     * @param string $data['product_id']     选填  商品 ID String(32)
     * @param string $data['limit_credit_pay']     选填  是否限制信用卡，限定用户使用时能否使用信用卡，值为1，禁用信用卡；值为0或者不传此参数则不禁用  String(32)
     *
     * ------------------------------------ 响应字段 -------------------------------------------
     * @param string $data['version']     必填   版本号，version默认值是2.0    String(8)
     * @param string $data['charset']    必填   字符集，默认为 UTF-8   String(8)
     * @param string $data['sign_type']  必填   签名方式  String(8)
     * @param string $data['status']   必填  返回状态码，0表示成功，非0表示失败此字段是通信标识，非交易标识，交易是否成功需要查看 result_code 来判断  String(16)
     * @param string $data['message']     选填  返回信息 String(128)
     *
     * 以下字段在 status 为 0的时候有返回
     *
     * @param string $data['result_code']   必填  业务结果，0表示成功，非0表示失败  String(16)
     * @param string $data['mch_id']       必填  商户号  	String(32)
     * @param string $data['device_info']  选填   设备号  String(32)
     * @param string $data['nonce_str']  必填   随机字符串  	String(32)
     * @param string $data['err_code']      选填   错误代码 String(32)
     * @param string $data['err_msg']   选填  错误代码描述  String (128)
     * @param string $data['sign']   必填  签名  String(32)
     *
     * 以下字段在 status 和 result_code 都为 0的时候有返回
     *
     * @param string $data['code_url']  必填   二维码链接  String(64)
     * @param string $data['code_img_url']  必填   二维码图片 String(256)
     *
     * @return array
     */
    private function nativePay($data){
        $this->reqHandler->setParameter('service','pay.weixin.native');//接口类型
        $this->reqHandler->setParameter('mch_id',$this->mchId);//必填项，商户号，由平台分配
        $this->reqHandler->setParameter('out_trade_no',$data['out_trade_no']);
        $this->reqHandler->setParameter('body',$data['body']);
        $this->reqHandler->setParameter('total_fee',$data['total_fee']);
        $this->reqHandler->setParameter('mch_create_ip',$_SERVER['REMOTE_ADDR']);
        $this->reqHandler->setParameter('limit_credit_pay','0');
        $this->reqHandler->setParameter('attach',empty($data['attach'])?'':$data['attach']);
        $this->reqHandler->setParameter('notify_url',$data['notifyUrl']);
        $this->reqHandler->setParameter('nonce_str',$this->getNonceStr());//随机字符串，必填项，不长于 32 位
        $this->reqHandler->createSign();//创建签名

        $data = Utils::toXml($this->reqHandler->getAllParameters());
        SnHelper::logFun('中信 nativePay 支付接口提交数据',$this->reqHandler->getAllParameters());
        $this->pay->setReqContent($this->reqHandler->getGateURL(),$data);
        if($this->pay->call()){
            $this->resHandler->setContent($this->pay->getResContent());
            $this->resHandler->setKey($this->reqHandler->getKey());
            if($this->resHandler->isTenpaySign()){
                SnHelper::logFun('中信 nativePay 支付接口返回数据',$this->reqHandler->getAllParameters());
                //当返回状态与业务结果都为0时才返回支付二维码，其它结果请查看接口文档
                if($this->resHandler->getParameter('status') == 0 && $this->resHandler->getParameter('result_code') == 0){
                    return ["code"=>0,"status"=>$this->resHandler->getParameter('result_code'),'msg'=>'操作成功','code_img_url'=>$this->resHandler->getParameter('code_img_url'),'data'=>$this->resHandler->getParameter('code_url')];
                }else{
                    return ["code"=>1,"status"=>$this->resHandler->getParameter('err_code'),'msg'=>$this->resHandler->getParameter('err_msg')];
                }
            }
            return ["code"=>1,"data_code"=>$this->resHandler->getParameter('status'),'msg'=>$this->resHandler->getParameter('message')];
        }else{
            return ["code"=>1,"data_code"=>$this->pay->getResponseCode(),'msg'=>$this->pay->getErrInfo()];
        }
    }

    /**
     * 微信内支付接口
     *
     * @param $data
     * ------------------------------------ 必填字段 -------------------------------------------
     * @param string $data['service']  必填 默认值:pay.weixin.native   接口类型     String(32)
     * @param string $data['mch_id']  必填   商户号  String(32)
     * @param string $data['is_raw']  必填   原生JS  String(1)
     *
     * @param string $data['out_trade_no']     必填  商户订单号  String(32)
     * @param string $data['body']   必填  商品描述  String(127)
     * @param string $data['sub_openid']   必填  用户openid,微信用户关注商家公众号的openid（注：使用测试号时此参数置空，即不要传这个参数，使用正式商户号时才传入，参数名是sub_openid，具体请看文档最后注意事项第7点）  String(128)
     * @param string $data['sub_appid']   必填  公众账号或小程序ID,当发起公众号支付时，值是微信公众平台基本配置中的AppID(应用ID)；当发起小程序支付时，值是对应小程序的AppID  String(32)
     * @param string $data['total_fee']       必填  总金额  Int
     * @param string $data['mch_create_ip']  必填   终端IP  String(16)
     * @param string $data['notify_url']  必填   通知地址  String(255)
     * @param string $data['nonce_str']      必填   随机字符串  String(32)
     * @param string $data['sign']   必填  签名  String(32)
     *
     * ------------------------------------ 选填字段 -------------------------------------------
     * @param string $data['version']     选填  版本号，version默认值是2.0  String(8)
     * @param string $data['charset']     选填  字符集，默认为 UTF-8  String(8)
     * @param string $data['sign_type']     选填  签名方式，默认：MD5 String(8)
     * @param string $data['is_minipg']     选填  是否小程序支付，值为1，表示小程序支付；不传或值不为1，表示公众账号内支付   String(1)
     * @param string $data['device_info']     选填  设备号  String(32)
     * @param string $data['attach']     选填  商户附加信息，可做扩展参数  String(127)
     * @param string $data['time_start']     选填  订单生成时间，订单生成时间，格式为yyyyMMddHHmmss 注：订单生成时间与超时时间需要同时传入才会生效。 String(14)
     * @param string $data['time_expire']     选填  订单失效时间，格式为yyyyMMddHHmmss 注：订单生成时间与超时时间需要同时传入才会生效。 String(14)
     * @param string $data['op_user_id']     选填  操作员，默认为商户号  String(32)
     * @param string $data['goods_tag']     选填  商品标记  String(32)
     * @param string $data['product_id']     选填  商品 ID String(32)
     * @param string $data['limit_credit_pay']     选填  是否限制信用卡，限定用户使用时能否使用信用卡，值为1，禁用信用卡；值为0或者不传此参数则不禁用  String(32)
     *
     * ------------------------------------ 响应字段 -------------------------------------------
     * @param string $data['appid']     选填   公众账号ID，服务商公众号APPID   String(32)
     * @param string $data['version']     必填   版本号，version默认值是2.0    String(8)
     * @param string $data['charset']    必填   字符集，默认为 UTF-8   String(8)
     * @param string $data['sign_type']  选填   签名方式  String(8)
     * @param string $data['status']   必填  返回状态码，0表示成功，非0表示失败此字段是通信标识，非交易标识，交易是否成功需要查看 result_code 来判断  String(16)
     * @param string $data['message']     选填  返回信息 String(128)
     *
     * 以下字段在 status 为 0的时候有返回
     *
     * @param string $data['result_code']   必填  业务结果，0表示成功，非0表示失败  String(16)
     * @param string $data['mch_id']       必填  商户号  	String(32)
     * @param string $data['device_info']  选填   设备号  String(32)
     * @param string $data['nonce_str']  必填   随机字符串  	String(32)
     * @param string $data['err_code']      选填   错误代码 String(32)
     * @param string $data['err_msg']   选填  错误代码描述  String (128)
     * @param string $data['sign']   必填  签名  String(32)
     *
     * 以下字段在 status 和 result_code 都为 0的时候有返回
     *
     * @param string $data['pay_info']  必填   原生态js支付信息或小程序支付信息,原生态js支付：is_raw为1时返回，json格式的字符串，作用于原生态js支付时的参数
    小程序支付：is_minipg为1时返回，json格式的字符串，作用于小程序支付时的参数  String
     *
     * @return array
     */
    private function jsapiPay($data){
        $this->reqHandler->setParameter('service','pay.weixin.jspay');//接口类型
        $this->reqHandler->setParameter('mch_id',$this->mchId);//必填项，商户号，由平台分配
        $this->reqHandler->setParameter('out_trade_no',$data['out_trade_no']);
        $this->reqHandler->setParameter('body',$data['body']);
        $this->reqHandler->setParameter('total_fee',$data['total_fee']);
        $this->reqHandler->setParameter('mch_create_ip',$_SERVER['REMOTE_ADDR']);
        $this->reqHandler->setParameter('limit_credit_pay','0');
        $this->reqHandler->setParameter('notify_url',$data['notifyUrl']);
        $this->reqHandler->setParameter('nonce_str',$this->getNonceStr());//随机字符串，必填项，不长于 32 位
        $this->reqHandler->setParameter('is_raw',1);
        $this->reqHandler->setParameter('is_minipg','0');
        $this->reqHandler->setParameter('attach',empty($data['attach'])?'':$data['attach']);
        if(empty($this->debug)){
            $this->reqHandler->setParameter('sub_openid',$data['sub_openid']);
            $this->reqHandler->setParameter('sub_appid',$this->appid);
        }

        $this->reqHandler->createSign();//创建签名

        $data = Utils::toXml($this->reqHandler->getAllParameters());
        SnHelper::logFun('中信 jsapiPay 支付接口返回数据',$this->reqHandler->getAllParameters());
        $this->pay->setReqContent($this->reqHandler->getGateURL(),$data);

        if($this->pay->call()){
            $this->resHandler->setContent($this->pay->getResContent());
            $this->resHandler->setKey($this->reqHandler->getKey());
            if($this->resHandler->isTenpaySign()){
                SnHelper::logFun('中信 jsapiPay 支付接口返回数据',$this->reqHandler->getAllParameters());
                //当返回状态与业务结果都为0时才返回支付二维码，其它结果请查看接口文档
                if($this->resHandler->getParameter('status') == 0 && $this->resHandler->getParameter('result_code') == 0){
                    return ["code"=>0,"status"=>$this->resHandler->getParameter('result_code'),'msg'=>'操作成功','data'=>$this->resHandler->getParameter('pay_info')];
                }else{
                    if(!empty($this->resHandler->getParameter('err_code'))){
                        return ["code"=>1,"status"=>$this->resHandler->getParameter('err_code'),'msg'=>$this->resHandler->getParameter('err_msg')];
                    }else{
                        return ["code"=>1,"status"=>$this->resHandler->getParameter('status'),'msg'=>$this->resHandler->getParameter('message')];
                    }
                }
            }
            return ["code"=>1,"status"=>$this->resHandler->getParameter('status'),'msg'=>$this->resHandler->getParameter('message')];
        }else{
            return ["code"=>1,"status"=>$this->pay->getResponseCode(),'msg'=>$this->pay->getErrInfo()];
        }
    }


    /**
	 * 退款接口
     *
     * @param $data
     * ------------------------------------ 请求字段 -------------------------------------------
     * @param string $data['service']  必填 默认值:unified.trade.refund   接口类型     String(32)
     * @param string $data['mch_id']  必填   商户号  String(32)
     * @param string $data['out_refund_no']  必填   商户退款单号,商户退款单号，32个字符内、可包含字母,确保在商户系统唯一。同个退款单号多次请求，平台当一个单处理，只会退一次款。如果出现退款不成功，请采用原退款单号重新发起，避免出现重复退款。  String(32)
     * @param string $data['total_fee']  必填   总金额,订单总金额，单位为分  Int
     * @param string $data['refund_fee']  必填   退款金额,退款总金额,单位为分,可以做部分退款  Int
     * @param string $data['op_user_id']  必填   操作员,操作员帐号,默认为商户号  String(32)
     * @param string $data['nonce_str']      必填   随机字符串  String(32)
     * @param string $data['sign']   必填  签名  String(32)
     *
     * ------------------------------------ 选填字段 -------------------------------------------
     * @param string $data['version']     选填  版本号，version默认值是2.0  String(8)
     * @param string $data['charset']     选填  字符集，默认为 UTF-8  String(8)
     * @param string $data['sign_type']     选填  签名方式，默认：MD5 String(8)
     * @param string $data['out_trade_no']     选填  商户订单号，商户系统内部的订单号, out_trade_no和transaction_id至少一个必填，同时存在时transaction_id优先   String(32)
     * @param string $data['transaction_id']     选填  平台订单号, out_trade_no和transaction_id至少一个必填，同时存在时transaction_id优先  String(32)
     * @param string $data['refund_channel']     选填  退款渠道，ORIGINAL-原路退款，默认 String(16)
     *
     *
     * ------------------------------------ 响应字段 -------------------------------------------
     * @param string $data['version']     必填   版本号，version默认值是2.0    String(8)
     * @param string $data['charset']    必填   字符集，默认为 UTF-8   String(8)
     * @param string $data['sign_type']  选填   签名方式  String(8)
     * @param string $data['status']   必填  返回状态码，0表示成功，非0表示失败此字段是通信标识，非交易标识，交易是否成功需要查看 result_code 来判断  String(16)
     * @param string $data['message']     选填  返回信息 String(128)
     *
     * 以下字段在 status 为 0的时候有返回
     *
     * @param string $data['result_code']   必填  0表示成功，非0表示失败 注：此处返回0表示退款申请接收成功，实际的退款结果根据退款查询接口查询  String(16)
     * @param string $data['mch_id']       必填  商户号  	String(32)
     * @param string $data['device_info']  选填   设备号  String(32)
     * @param string $data['nonce_str']  必填   随机字符串  	String(32)
     * @param string $data['err_code']      选填   错误代码 String(32)
     * @param string $data['sign']   必填  签名  String(32)
     *
     * 以下字段在 status 和 result_code 都为 0的时候有返回
     *
     * @param string $data['transaction_id']  必填 平台订单号  String(32)
     * @param string $data['out_trade_no']  必填 商户订单号,商户系统内部的订单号  String(32)
     * @param string $data['out_refund_no']  必填 商户退款单号  String(32)
     * @param string $data['refund_id']  必填 平台退款单号  String(32)
     * @param string $data['refund_channel']  必填 退款渠道,ORIGINAL—原路退款，默认  String(16)
     * @param string $data['refund_fee']  必填 退款金额,退款总金额,单位为分,可以做部分退款  Int
     * @param string $data['coupon_refund_fee']  选填 现金券退款金额,现金券退款金额 <= 退款金额， 退款金额-现金券退款金额为现金  Int
     *
     * @return array
	 */
    public function refund($data){
        if(empty($this->mchId)){
            return ['code'=>1,'msg'=>'此商城支付系统正在升级'];
        }

        if(empty($data['transaction_id']) && empty($data['out_trade_no'])){
            return ["code"=>1,'msg'=>'请输入商户订单号或平台订单号!'];
        }

        if(empty($data['out_refund_no'])){
            return ["code"=>1,"msg"=>'商户退款单号不能为空'];
        }

        if(empty($data['total_fee'])){
            return ["code"=>1,"msg"=>'总金额不能为空'];
        }

        if(empty($data['refund_fee'])){
            return ["code"=>1,"msg"=>'退款金额不能为空'];
        }

        $this->reqHandler->setParameter('out_trade_no',empty($data['out_trade_no'])?'':$data['out_trade_no']);
        $this->reqHandler->setParameter('out_refund_no',$data['out_refund_no']);
        $this->reqHandler->setParameter('total_fee',$data['total_fee']);
        $this->reqHandler->setParameter('refund_fee',$data['refund_fee']);
        $this->reqHandler->setParameter('transaction_id',empty($data['transaction_id'])?'':$data['transaction_id']);
        $this->reqHandler->setParameter('service','unified.trade.refund');//接口类型
        $this->reqHandler->setParameter('mch_id',$this->mchId);//必填项，商户号，由平台分配
        $this->reqHandler->setParameter('nonce_str',$this->getNonceStr());//随机字符串，必填项，不长于 32 位
        $this->reqHandler->setParameter('op_user_id',$this->mchId);//必填项，操作员帐号,默认为商户号
        $this->reqHandler->createSign();//创建签名

        $data = Utils::toXml($this->reqHandler->getAllParameters());//将提交参数转为xml，目前接口参数也只支持XML方式
        SnHelper::logFun('中信 退款接口提交数据',$this->reqHandler->getAllParameters());
        $this->pay->setReqContent($this->reqHandler->getGateURL(),$data);
        if($this->pay->call()){
            $this->resHandler->setContent($this->pay->getResContent());
            $this->resHandler->setKey($this->reqHandler->getKey());
            if($this->resHandler->isTenpaySign()){
                $res = $this->resHandler->getAllParameters();
                SnHelper::logFun('中信 退款接口返回数据',$res);
                //当返回状态与业务结果都为0时才返回，其它结果请查看接口文档
                if($this->resHandler->getParameter('status') == 0 && $this->resHandler->getParameter('result_code') == 0){
                    return ["code"=>0,"status"=>$this->resHandler->getParameter('result_code'),'msg'=>'退款成功','data'=>$res];
                }else{
                    return ["code"=>1,"status"=>$this->resHandler->getParameter('err_code'),'msg'=>$this->resHandler->getParameter('err_msg')];
                }
            }
            return ["code"=>1,"status"=>$this->resHandler->getParameter('status'),'msg'=>$this->resHandler->getParameter('message')];
        }else{
            return ["code"=>1,"status"=>$this->pay->getResponseCode(),'msg'=>$this->pay->getErrInfo()];
        }

    }

    /**
     * 查询订单
     *
     * @param $data
     * ------------------------------------ 请求字段 -------------------------------------------
     * @param string $data['service']  必填 默认值:unified.trade.query   接口类型     String(32)
     * @param string $data['mch_id']  必填   商户号  String(32)
     * @param string $data['nonce_str']      必填   随机字符串  String(32)
     * @param string $data['sign']   必填  签名  String(32)
     *
     * ------------------------------------ 选填字段 -------------------------------------------
     * @param string $data['version']     选填  版本号，version默认值是2.0  String(8)
     * @param string $data['charset']     选填  字符集，默认为 UTF-8  String(8)
     * @param string $data['sign_type']     选填  签名方式，默认：MD5 String(8)
     * @param string $data['out_trade_no']     选填  商户订单号，商户系统内部的订单号,out_trade_no和transaction_id至少一个必填，同时存在时transaction_id优先   String(32)
     * @param string $data['transaction_id']     选填  平台订单号, out_trade_no和transaction_id至少一个必填，同时存在时transaction_id优先  String(32)
     *
     * ------------------------------------ 响应字段 -------------------------------------------
     * @param string $data['version']     必填   版本号，version默认值是2.0    String(8)
     * @param string $data['charset']    必填   字符集，默认为 UTF-8   String(8)
     * @param string $data['sign_type']  选填   签名方式  String(8)
     * @param string $data['status']   必填  返回状态码，0表示成功，非0表示失败此字段是通信标识，非交易标识，交易是否成功需要查看 result_code 来判断  String(16)
     * @param string $data['message']     选填  返回信息 String(128)
     *
     * 以下字段在 status 为 0的时候有返回
     *
     * @param string $data['result_code']   必填  0表示成功，非0表示失败  String(16)
     * @param string $data['mch_id']       必填  商户号  	String(32)
     * @param string $data['device_info']  选填   设备号  String(32)
     * @param string $data['nonce_str']  必填   随机字符串  	String(32)
     * @param string $data['err_code']      选填   错误代码 String(32)
     * @param string $data['sign']   必填  签名  String(32)
     *
     * 以下字段在 status 和 result_code 都为 0的时候有返回
     *
     * @param string $data['trade_state']  必填 交易状态,SUCCESS—支付成功REFUND—转入退款 NOTPAY—未支付CLOSED—已关闭 PAYERROR—支付失败(其他原因，如银行返回失败)  String(32)
     *
     * 以下字段在 trade_state 为 SUCCESS 的时候有返回
     * @param string $data['trade_type']  必填 交易类型,pay.weixin.native  String(32)
     * @param string $data['appid']  必填 公众号appid,服务商公众号appid  String(32)
     * @param string $data['openid']  必填 用户标识,用户在服务商 appid 下的唯一标识  String(32)
     * @param string $data['is_subscribe']  必填 是否关注公众账号,用户是否关注服务商公众账号，Y-关注，N-未关注 String(1)
     * @param string $data['transaction_id']  必填 平台订单号,平台交易单号  String(32)
     * @param string $data['out_transaction_id']  选填 第三方订单号,第三方订单号（支付成功后会返回，没支付则不会）  String(32)
     * @param string $data['out_trade_no']  必填 商户订单号,商户系统内部的定单号，32个字符内、可包含字母  String(32)
     * @param string $data['total_fee']  必填 总金额，以分为单位，不允许包含任何字、符号  Int
     * @param string $data['coupon_fee']  选填 现金券金额,现金券支付金额<=订单总金额， 订单总金额-现金券金额为现金支付金额  Int
     * @param string $data['fee_type']  必填 货币种类，符合 ISO 4217 标准的三位字母代码，默认人民币：CNY  String(8)
     * @param string $data['attach']  选填 附加信息,商家数据包，原样返回  String(127)
     * @param string $data['bank_type']  必填 付款银行,银行类型  String(16)
     * @param string $data['bank_billno']  选填 银行订单号，若为微信支付则为空  String(32)
     * @param string $data['time_end']  必填 支付完成时间，格式为yyyyMMddHHmmss，如2009年12月27日9点10分10秒表示为20091227091010。时区为GMT+8 beijing。该时间取自平台服务器  String(14)
     *
     * @return array
     */
    public function checkPay($data){
        if(empty($this->mchId)){
            return ['code'=>1,'msg'=>'此商城支付系统正在升级'];
        }

        if(empty($data['transaction_id']) && empty($data['out_trade_no'])){
            return ["code"=>1,'msg'=>'请输入商户订单号或平台订单号!'];
        }

        $this->reqHandler->setParameter('service','unified.trade.query');//接口类型：
        $this->reqHandler->setParameter('out_trade_no',empty($data['out_trade_no'])?'':$data['out_trade_no']);
        $this->reqHandler->setParameter('mch_id',$this->mchId);//必填项，商户号，由平台分配
        $this->reqHandler->setParameter('nonce_str',$this->getNonceStr());//随机字符串，必填项，不长于 32 位
        $this->reqHandler->setParameter('transaction_id',empty($data['transaction_id'])?'':$data['transaction_id']);

        $this->reqHandler->createSign();//创建签名
        $data = Utils::toXml($this->reqHandler->getAllParameters());
        SnHelper::logFun('中信 查询订单提交数据',$this->reqHandler->getAllParameters());
        $this->pay->setReqContent($this->reqHandler->getGateURL(),$data);
        if($this->pay->call()){
            $this->resHandler->setContent($this->pay->getResContent());
            $this->resHandler->setKey($this->reqHandler->getKey());
            if($this->resHandler->isTenpaySign()){
                $res = $this->resHandler->getAllParameters();
                SnHelper::logFun('中信 查询订单返回数据',$res);
                //当返回状态与业务结果都为0时才返回，其它结果请查看接口文档
                if($this->resHandler->getParameter('status') == 0 && $this->resHandler->getParameter('result_code') == 0){
                    //支付成功会输出更多参数，详情请查看文档中的7.1.4返回结果
                    if($this->resHandler->getParameter('trade_state') == 'SUCCESS'){
                        return ["code"=>0,"status"=>$this->resHandler->getParameter('trade_state'),'msg'=>$this->resHandler->getParameter('trade_state_desc'),'data'=>$res];
                    }else{
                        return ["code"=>0,"status"=>$this->resHandler->getParameter('result_code'),'msg'=>'查询订单成功','data'=>$res];
                    }

                }else{
                    return ["code"=>1,"status"=>$this->resHandler->getParameter('err_code'),'msg'=>$this->resHandler->getParameter('err_msg')];
                }

            }
            return ["code"=>1,"status"=>$this->resHandler->getParameter('status'),'msg'=>$this->resHandler->getParameter('message')];
        }else{
            return ["code"=>1,"status"=>$this->pay->getResponseCode(),'msg'=>$this->pay->getErrInfo()];
        }
    }

    /**
     * 退款查询
     *
     * @param $data
     * ------------------------------------ 请求字段 -------------------------------------------
     * @param string $data['service']  必填 默认值:unified.trade.refundquery   接口类型     String(32)
     * @param string $data['mch_id']  必填   商户号  String(32)
     * @param string $data['nonce_str']      必填   随机字符串  String(32)
     * @param string $data['sign']   必填  签名  String(32)
     *
     * ------------------------------------ 选填字段 -------------------------------------------
     * @param string $data['version']     选填  版本号，version默认值是2.0  String(8)
     * @param string $data['charset']     选填  字符集，默认为 UTF-8  String(8)
     * @param string $data['sign_type']     选填  签名方式，默认：MD5 String(8)
     * @param string $data['out_trade_no']     选填  商户订单号，商户系统内部的订单号,out_trade_no和transaction_id至少一个必填，同时存在时transaction_id优先   String(32)
     * @param string $data['transaction_id']     选填  平台订单号, out_trade_no和transaction_id至少一个必填，同时存在时transaction_id优先  String(32)
     * @param string $data['out_refund_no']     选填  商户退款单号，32个字符内、可包含字母,确保在商户系统唯一。  String(32)
     * @param string $data['refund_id']     选填  平台退款单号，平台退款单号refund_id、out_refund_no、out_trade_no 、transaction_id 四个参数必填一个， 如果同事存在优先级为：refund_id>out_refund_no>transaction_id>out_trade_no  String(32)
     *
     * ------------------------------------ 响应字段 -------------------------------------------
     * @param string $data['version']     必填   版本号，version默认值是2.0    String(8)
     * @param string $data['charset']    必填   字符集，默认为 UTF-8   String(8)
     * @param string $data['sign_type']  选填   签名方式  String(8)
     * @param string $data['status']   必填  返回状态码，0表示成功，非0表示失败此字段是通信标识，非交易标识，交易是否成功需要查看 result_code 来判断  String(16)
     * @param string $data['message']     选填  返回信息 String(128)
     *
     * 以下字段在 status 为 0的时候有返回
     *
     * @param string $data['result_code']   必填  0表示成功，非0表示失败  String(16)
     * @param string $data['mch_id']       必填  商户号  	String(32)
     * @param string $data['device_info']  选填   设备号  String(32)
     * @param string $data['nonce_str']  必填   随机字符串  	String(32)
     * @param string $data['err_code']      选填   错误代码 String(32)
     * @param string $data['sign']   必填  签名  String(32)
     *
     * 以下字段在 status 和 result_code 都为 0的时候有返回
     *
     * @param string $data['transaction_id']  必填 平台订单号,平台交易号。  String(32)
     * @param string $data['out_trade_no']  必填 商户订单号,商户系统内部的订单号  String(32)
     * @param string $data['refund_count']  必填 退款记录数  Int
     * @param string $data['out_refund_no_$n']  必填 商户退款单号  String(32)
     * @param string $data['refund_id_$n']  必填 平台退款单号 String(32)
     * @param string $data['refund_channel_$n']  必填 退款渠道,ORIGINAL—原路退款，默认  String(16)
     * @param string $data['refund_fee_$n']  必填 退款金额,退款总金额,单位为分,可以做部分退款  Int
     * @param string $data['coupon_refund_fee_$n']  选填 现金券退款金额 <= 退款金额， 退款金额-现金券退款金额为现金  Int
     * @param string $data['refund_time_$n']  选填 退款时间，yyyyMMddHHmmss  String(14)
     * @param string $data['refund_status_$n']  必填 退款状态,退款状态：SUCCESS—退款成功 FAIL—退款失败 PROCESSING—退款处理中 NOTSURE—未确定， 需要商户原退款单号重新发起 CHANGE—转入代发，退款到银行发现用户的卡作废或者冻结了，导致原路退款银行卡失败，资金回流到商户的现金帐号，需要商户人工干预，通过线下或者平台转账的方式进行退款。  	String(16)
     *
     * $n 表示记录的序号，取值为 0~($ refund_count -1)，例如 refund_count 指示返回的退款记录有 2 条。第一条序号为“0”，第二条序号为“1”。
     *
     * @return array
     */
    public function checkRefund($data){
        if(empty($this->mchId)){
            return ['code'=>1,'msg'=>'此商城支付系统正在升级'];
        }

        if(empty($data['transaction_id']) && empty($data['out_trade_no']) && empty($data['out_refund_no']) && empty($data['refund_id'])){
            return ["code"=>1,'msg'=>'请输入商户订单号、平台订单号、商户退款单号或平台退款单号!'];
        }

        $this->reqHandler->setParameter('service','unified.trade.refundquery');//接口类型
        $this->reqHandler->setParameter('mch_id',$this->mchId);//必填项，商户号，由平台分配
        $this->reqHandler->setParameter('nonce_str',$this->getNonceStr());//随机字符串，必填项，不长于 32 位

        $this->reqHandler->setParameter('transaction_id',empty($data['transaction_id'])?'':$data['transaction_id']);
        $this->reqHandler->setParameter('out_trade_no',empty($data['out_trade_no'])?'':$data['out_trade_no']);
        $this->reqHandler->setParameter('out_refund_no',empty($data['out_refund_no'])?'':$data['out_refund_no']);
        $this->reqHandler->setParameter('refund_id',empty($data['refund_id'])?'':$data['refund_id']);

        $this->reqHandler->createSign();//创建签名
        $data = Utils::toXml($this->reqHandler->getAllParameters());//将提交参数转为xml，目前接口参数也只支持XML方式
        SnHelper::logFun('中信 查询退款提交数据',$this->reqHandler->getAllParameters());
        $this->pay->setReqContent($this->reqHandler->getGateURL(),$data);//设置请求地址与请求参数
        if($this->pay->call()){
            $this->resHandler->setContent($this->pay->getResContent());
            $this->resHandler->setKey($this->reqHandler->getKey());
            if($this->resHandler->isTenpaySign()){

                $res = $this->resHandler->getAllParameters();
                SnHelper::logFun('中信 查询退款返回数据',$res);
                //当返回状态与业务结果都为0时才返回，其它结果请查看接口文档
                if($this->resHandler->getParameter('status') == 0 && $this->resHandler->getParameter('result_code') == 0){
                    return ["code"=>0,"status"=>$this->resHandler->getParameter('result_code'),'msg'=>'查询成功','data'=>$res];
                }else{
                    return ["code"=>1,"status"=>$this->resHandler->getParameter('err_code'),'msg'=>$this->resHandler->getParameter('err_msg')];
                }
            }
            return ["code"=>1,"status"=>$this->resHandler->getParameter('status'),'msg'=>$this->resHandler->getParameter('message')];
        }else{
            return ["code"=>1,"status"=>$this->pay->getResponseCode(),'msg'=>$this->pay->getErrInfo()];
        }
    }

    /**
     * 关闭订单
     *
     * @param $data
     * ------------------------------------ 请求字段 -------------------------------------------
     * @param string $data['service']  必填 默认值:unified.trade.close   接口类型     String(32)
     * @param string $data['mch_id']  必填   商户号  String(32)
     * @param string $data['out_trade_no']     选填  商户订单号，商户系统内部的订单号 ,32个字符内、 可包含字母,确保在商户系统唯一   String(32)
     * @param string $data['nonce_str']      必填   随机字符串  String(32)
     * @param string $data['sign']   必填  签名  String(32)
     *
     * ------------------------------------ 选填字段 -------------------------------------------
     * @param string $data['version']     选填  版本号，version默认值是2.0  String(8)
     * @param string $data['charset']     选填  字符集，默认为 UTF-8  String(8)
     * @param string $data['sign_type']     选填  签名方式，默认：MD5 String(8)
     *
     * ------------------------------------ 响应字段 -------------------------------------------
     * @param string $data['version']     必填   版本号，version默认值是2.0    String(8)
     * @param string $data['charset']    必填   字符集，默认为 UTF-8   String(8)
     * @param string $data['sign_type']  选填   签名方式  String(8)
     * @param string $data['status']   必填  返回状态码，0表示成功，非0表示失败此字段是通信标识，非交易标识，交易是否成功需要查看 result_code 来判断  String(16)
     * @param string $data['message']     选填  返回信息 String(128)
     *
     * 以下字段在 status 为 0的时候有返回
     *
     * @param string $data['result_code']   必填  	0表示成功，非0表示失败；0表示关单成功，此笔订单不能再发起支付；若已支付完成，则会发起退款；非0或其它表示关单接口异常，可再次发起关单操作；  String(16)
     * @param string $data['mch_id']       必填  商户号  	String(32)
     * @param string $data['nonce_str']  必填   随机字符串  	String(32)
     * @param string $data['err_code']      选填   错误代码 String(32)
     * @param string $data['err_msg']      选填   错误代码描述 String (128)
     * @param string $data['sign']   必填  签名  String(32)
     *
     * @return array
     */
    public function closeOrder($data){
        if(empty($this->mchId)){
            return ['code'=>1,'msg'=>'此商城支付系统正在升级'];
        }

        if(empty($data['transaction_id']) && empty($data['out_trade_no'])){
            return ["code"=>1,'msg'=>'请输入商户订单号或平台订单号!'];
        }

        $this->reqHandler->setParameter('service','unified.trade.close');//接口类型
        $this->reqHandler->setParameter('mch_id',$this->mchId);//必填项，商户号，由平台分配
        $this->reqHandler->setParameter('nonce_str',$this->getNonceStr());//随机字符串，必填项，不长于 32 位
        $this->reqHandler->setParameter('transaction_id',empty($data['transaction_id'])?'':$data['transaction_id']);
        $this->reqHandler->setParameter('out_trade_no',empty($data['out_trade_no'])?'':$data['out_trade_no']);
        $this->reqHandler->createSign();//创建签名
        $data = Utils::toXml($this->reqHandler->getAllParameters());
        SnHelper::logFun('中信 关闭订单提交数据',$this->reqHandler->getAllParameters());
        $this->pay->setReqContent($this->reqHandler->getGateURL(),$data);
        if($this->pay->call()){
            $this->resHandler->setContent($this->pay->getResContent());
            $this->resHandler->setKey($this->reqHandler->getKey());
            if($this->resHandler->isTenpaySign()){
                $res = $this->resHandler->getAllParameters();
                SnHelper::logFun('中信 关闭订单返回数据',$res);
                //当返回状态与业务结果都为0时才返回，其它结果请查看接口文档
                if($this->resHandler->getParameter('status') == 0 && $this->resHandler->getParameter('result_code') == 0){
                    return ["code"=>0,"status"=>$this->resHandler->getParameter('result_code'),'msg'=>'查询成功','data'=>$res];
                }else{
                    return ["code"=>1,"status"=>$this->resHandler->getParameter('err_code'),'msg'=>$this->resHandler->getParameter('err_msg')];
                }
            }
            return ["code"=>1,"status"=>$this->resHandler->getParameter('status'),'msg'=>$this->resHandler->getParameter('message')];
        }else{
            return ["code"=>1,"status"=>$this->pay->getResponseCode(),'msg'=>$this->pay->getErrInfo()];
        }
    }

    /**
     * 对账单下载
     *
     * @param $data
     * ------------------------------------ 请求字段 -------------------------------------------
     * @param string $data['service']  必填   接口类型 接口类型参数值：（与传入的mch_id的类型对应）pay.bill.merchant：下载单个商户时的对账单 pay.bill.bigMerchant：下载连锁商户下所有门店的对账单 pay.bill.agent：下载某内部机构/外包服务机构下所有商户的对账单     String(32)
     * @param string $data['bill_date']  必填   账单日期,格式：yyyyMMdd(如：20150101)  String(32)
     * @param string $data['bill_type']     必填  账单类型，ALL，返回支付成功和转入退款的订单，默认值 SUCCESS，返回支付成功的订单 REFUND，返回转入退款的订单  String(8)
     * @param string $data['mch_id']      必填   商户号/连锁商户号/机构号,商户号/连锁商户号/机构号，分别对应下载单个商户、连锁商户、内部机构/外包服务机构类型对账单，由威富通分配  String(32)
     * @param string $data['nonce_str']      必填   随机字符串  String(32)
     * @param string $data['sign']   必填  签名  String(32)
     *
     * ------------------------------------ 选填字段 -------------------------------------------
     * @param string $data['version']     选填  版本号，version默认值是2.0  String(8)
     * @param string $data['charset']     选填  字符集，默认为 UTF-8  String(8)
     * @param string $data['sign_type']     选填  签名方式，默认：MD5 String(8)
     *
     * ------------------------------------ 响应字段 -------------------------------------------
     * 第一行为表头
     * 交易时间,公众账号ID,第三方商户号,商户号,子商户号,设备编号,平台订单号,第三方订单号,商户订单号,用户标识,交易类型,交易状态,付款银行,货币种类,总金额,企业红包金额,平台退款单号,商户退款单号,退款金额,企业红包退款金额,退款类型,退款状态,商品名称,商户数据包,手续费,费率,终端类型,对账标识,门店编号,商户名称,收银员,子商户ID,免充值券金额,扩展字段1,扩展字段2,扩展字段3,扩展字段4：
     *
     * 第二行起为明细
     * 字段以","分割，每个字段前面统一加上"`"(Tab键上面)
     *
     * 最后两行会汇总信息
     * 总交易单数	总交易额	总退款金额	总企业红包退款金额	手续费总金额	总实收金额
     *
     * 示列如下
     * `2017-01-0508:48:32,`wx1f87d44db95cba7a,`,`,`7551000001,`,`7551000001201701057097816171,`4005332001201701055233761762`0481072323682611,`oywgtuEvm_X51EqpR8SZQRlrf2Rs,`pay.weixin.native,`支付成功,`ICBC_CREDIT,`CNY,`0.01,`,`,`,`,`,`,`,`测试购买商品,`附加信息,`0.00,`1.10%,`,`0,`,`银行线上测试,`,`oHmbkt3YXtBTpfInKu-KGkrASC-g,`
     *
     * 总交易单数,总交易额,总退款金额,总企业红包退款金额,总手续费金额,总实收金额
     * `1,`0.01,`0,`0,`0
     * @return array
     */
    public function payBill($data){
        if(empty($this->mchId)){
            return ['code'=>1,'msg'=>'此商城支付系统正在升级'];
        }

        if(!empty($data['type']) && !in_array($data['type'],['merchant','bigMerchant','agent'])){
            return ['code'=>1,'msg'=>'接口类型错误,可用类型为merchant，bigMerchant，agent'];
        }

        if(!empty($data['bill_type']) && !in_array($data['bill_type'],['ALL','SUCCESS','REFUND'])){
            return ['code'=>1,'msg'=>'账单类型错误,可用类型为ALL，SUCCESS，REFUND'];
        }

        if(empty($data['type'])){
            $data['type'] = 'merchant';
        }

        if($data['type'] == 'merchant'){
            $this->reqHandler->setParameter('service','pay.bill.merchant');//接口类型
        }elseif($data['type'] == 'bigMerchant'){
            $this->reqHandler->setParameter('service','pay.bill.bigMerchant');//接口类型
        }elseif($data['type'] == 'agent'){
            $this->reqHandler->setParameter('service','pay.bill.agent');//接口类型
        }else{
            $this->reqHandler->setParameter('service','pay.bill.merchant');//接口类型
        }

        $this->reqHandler->setParameter('bill_date',date('Ymd'));
        if(!empty($data['bill_date'])){
            $this->reqHandler->setParameter('bill_date',$data['bill_date']);
        }

        $this->reqHandler->setParameter('bill_type','ALL');
        if(!empty($data['bill_type'])){
            $this->reqHandler->setParameter('bill_type',$data['bill_type']);
        }

        $this->reqHandler->setParameter('mch_id',$this->mchId);//必填项，商户号，由平台分配
        $this->reqHandler->setParameter('nonce_str',$this->getNonceStr());//随机字符串，必填项，不长于 32 位

        $this->reqHandler->createSign();//创建签名
        $data = Utils::toXml($this->reqHandler->getAllParameters());
        SnHelper::logFun('中信 对账单下载提交数据',$this->reqHandler->getAllParameters());
        $this->pay->setReqContent($this->reqHandler->getGateURL(),$data);
        if($this->pay->call()){
            $this->resHandler->setContent($this->pay->getResContent());
            $this->resHandler->setKey($this->reqHandler->getKey());
            if($this->resHandler->isTenpaySign()){
                $res = $this->resHandler->getAllParameters();
                SnHelper::logFun('中信 对账单下载返回数据',$res);
                //当返回状态与业务结果都为0时才返回，其它结果请查看接口文档
                if($this->resHandler->getParameter('status') == 0 && $this->resHandler->getParameter('result_code') == 0){
                    return ["code"=>0,"status"=>$this->resHandler->getParameter('result_code'),'msg'=>'查询成功','data'=>$res];
                }else{
                    return ["code"=>1,"status"=>$this->resHandler->getParameter('err_code'),'msg'=>$this->resHandler->getParameter('err_msg')];
                }
            }
            return ["code"=>1,"status"=>$this->resHandler->getParameter('status'),'msg'=>$this->resHandler->getParameter('message')];
        }else{
            return ["code"=>1,"status"=>$this->pay->getResponseCode(),'msg'=>$this->pay->getErrInfo()];
        }
    }

    /**
     * 中信支付回调
     *
     * @param Request $request
     * @return array
     */
    public function notify(Request $request)
    {
        $xml = $request->getContent();
        $this->resHandler->setContent($xml);

        $data["out_trade_no"] = $this->resHandler->getParameter('out_trade_no');
        $config = $this->getZhongXinConfig();

        if(!empty($config['public_rsa_key']) && !empty($config['private_rsa_key'])){
            $this->reqHandler->setSignType('RSA_1_256');
            $this->reqHandler->setRSAKey($config['private_rsa_key']);
            $this->reqHandler->setParameter('sign_type','RSA_1_256');

            $this->resHandler->setRSAKey($config['public_rsa_key']);
            $this->resHandler->setSignType('RSA_1_256');
            $this->resHandler->setParameter('sign_type','RSA_1_256');
        }else{
            $zhongxin_key = $config['key'];
            $this->reqHandler->setSignType('MD5');
            $this->reqHandler->setKey($zhongxin_key);
            $this->reqHandler->setParameter('sign_type','MD5');

            $this->resHandler->setKey($zhongxin_key);
            $this->resHandler->setSignType('MD5');
            $this->resHandler->setParameter('sign_type','MD5');
        }

        if($config['debug']){
            return ['code'=>0,'data'=>$this->resHandler];
        }
        if($this->resHandler->isTenpaySign() && $this->resHandler->getParameter('status') == 0 && $this->resHandler->getParameter('result_code') == 0){
            //校验单号和金额是否一致，更改订单状态等业务处理
            return ['code'=>0,'data'=>$this->resHandler];
        }
        return ['code'=>1,'msg'=>'签名错误','data'=>$this->resHandler];
    }

    public function getZhongXinConfig()
    {
        $zhongxin_config['appid'] = $this->appid;
        $zhongxin_config['key'] = $this->key;
        $zhongxin_config['mchId'] = $this->mchId;
        $zhongxin_config['post_url'] = $this->post_url;
        $zhongxin_config['public_rsa_key'] = $this->public_rsa_key;
        $zhongxin_config['private_rsa_key'] = $this->private_rsa_key;
        $zhongxin_config['debug'] = $this->debug;

        return $zhongxin_config;
    }

    /**
     *
     * 产生随机字符串，不长于32位
     * @param int $length
     * @return string 产生的随机字符串
     */
    public static function getNonceStr($length = 32)
    {
        $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
        $str ="";
        for ( $i = 0; $i < $length; $i++ )  {
            $str .= substr($chars, mt_rand(0, strlen($chars)-1), 1);
        }
        return $str;
    }
}